package com.peas.platform.module.icims.expenditure.expenses.api;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.peas.platform.common.core.dto.ResponseDto;
import com.peas.platform.common.core.enums.BaseEnum;
import com.peas.platform.common.core.vo.BaseVo;
import com.peas.platform.framework.mybatisplus.utils.PageUtil;
import com.peas.platform.module.icims.expenditure.basal.enums.ExpenditureAccountType;
import com.peas.platform.module.icims.expenditure.expenses.api.req.*;
import com.peas.platform.module.icims.expenditure.expenses.api.resp.QueryExpenditureApplicationResp;
import com.peas.platform.module.icims.expenditure.expenses.api.resp.QueryExpenditureReimbursementResp;
import com.peas.platform.module.icims.expenditure.expenses.controller.criteria.ExpenditureApplicationCriteria;
import com.peas.platform.module.icims.expenditure.expenses.dto.ExpenditureApplicationDto;
import com.peas.platform.module.icims.expenditure.expenses.dto.ExpenditureReimbursementDto;
import com.peas.platform.module.icims.expenditure.expenses.dto.ExpenditureReimbursementPayDto;
import com.peas.platform.module.icims.expenditure.expenses.dto.ExpenditureReimbursementPayeeDto;
import com.peas.platform.module.icims.expenditure.expenses.service.ExpenditureApplicationService;
import com.peas.platform.module.icims.expenditure.expenses.service.ExpenditureReimbursementPayService;
import com.peas.platform.module.icims.expenditure.expenses.service.ExpenditureReimbursementPayeeService;
import com.peas.platform.module.icims.expenditure.expenses.service.ExpenditureReimbursementService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Api(tags = "自定义接口-[收支控制]报账管理")
@RestController
@RequestMapping("/api/v1/customExpenditureExpenses")
@Slf4j
public class CustomExpenditureExpensesController {

    @Resource
    private ExpenditureApplicationService expenditureApplicationService;
    @Resource
    private ExpenditureReimbursementService expenditureReimbursementService;
    @Resource
    private ExpenditureReimbursementPayeeService expenditureReimbursementPayeeService;
    @Resource
    private ExpenditureReimbursementPayService expenditureReimbursementPayService;

    @ApiOperation(value = "查询申请单可用金额")
    @GetMapping(value = "/queryExpenditureApplicationAvailableAmount")
    public ResponseDto<BigDecimal> queryExpenditureApplicationAvailableAmount(@RequestParam(value = "expenditureApplicationId") Long expenditureApplicationId) {
        Assert.notNull(expenditureApplicationId, "指标单ID不能为空");
        ExpenditureApplicationDto dto = expenditureApplicationService.getById(expenditureApplicationId);
        Assert.notNull(dto, "找不到事前用款申请单");
        BigDecimal totalReimbursementAmount = expenditureApplicationService.getTotalReimbursementAmount(expenditureApplicationId);
        return ResponseDto.getSuccessResponseDto(dto.getAmount().subtract(totalReimbursementAmount));
    }

    @ApiOperation(value = "查询申请单列表(包含总已报账金额)")
    @GetMapping(value = "/queryExpenditureApplication")
    public ResponseDto<Page<QueryExpenditureApplicationResp>> queryExpenditureApplication(ExpenditureApplicationCriteria condition,
                                                                                          @ApiParam(name = "pageNum", value = "分页页码", example = "1") Integer pageNum,
                                                                                          @ApiParam(name = "pageSize", value = "分页每页大小", example = "10") Integer pageSize,
                                                                                          @ApiParam(name = "sortField", value = "排序字段", example = "id") String sortField,
                                                                                          @ApiParam(name = "sortType", value = "排序方式", example = "desc") String sortType) {
        Page<ExpenditureApplicationDto> pager = PageUtil.genPager(pageNum, pageSize, sortField, sortType);
        ExpenditureApplicationDto c = BeanUtil.copyProperties(condition, ExpenditureApplicationDto.class);
        Page<ExpenditureApplicationDto> page = expenditureApplicationService.page(pager, c);
        Page<QueryExpenditureApplicationResp> vos = PageUtil.copyPage(page, QueryExpenditureApplicationResp.class);
        if (CollUtil.isNotEmpty(vos.getRecords())) {
            vos.getRecords().forEach(item -> {
                // 总报账金额
                item.setTotalReimbursementAmount(expenditureApplicationService.getTotalReimbursementAmount(item.getId()));
            });
        }
        return ResponseDto.getSuccessResponseDto(vos);
    }

    @ApiOperation(value = "查询报账单列表(包含支付、收款信息)")
    @GetMapping(value = "/queryExpenditureReimbursement/{ids}")
    public ResponseDto<List<QueryExpenditureReimbursementResp>> queryExpenditureReimbursement(@PathVariable(value = "ids") String ids) {
        List<Long> idArr = StrUtil.split(ids, ",").stream().map(Long::parseLong).collect(Collectors.toList());
        List<ExpenditureReimbursementDto> list = expenditureReimbursementService.listByIds(idArr);
        List<QueryExpenditureReimbursementResp> resps = new ArrayList<>();
        final List<ExpenditureReimbursementPayeeDto> payees = new ArrayList<>();
        final List<ExpenditureReimbursementPayDto> pays = new ArrayList<>();
        if (CollUtil.isNotEmpty(idArr)) {
            payees.addAll(expenditureReimbursementPayeeService.listByField("expenditureReimbursementId", idArr));
            pays.addAll(expenditureReimbursementPayService.listByField("expenditureReimbursementId", idArr));
        }
        log.debug("payees:" + payees);
        log.debug("pays:" + pays);
        CollUtil.forEach(list, (CollUtil.Consumer<ExpenditureReimbursementDto>) (o, index) -> {
            QueryExpenditureReimbursementResp er = BeanUtil.copyProperties(o, QueryExpenditureReimbursementResp.class);
            ExpenditureReimbursementPayeeDto payee = payees.stream().filter(erp -> NumberUtil.equals(o.getId(), erp.getExpenditureReimbursementId())).findFirst().orElse(null);
            ExpenditureReimbursementPayDto pay = pays.stream().filter(erp -> NumberUtil.equals(o.getId(), erp.getExpenditureReimbursementId())).findFirst().orElse(null);
            log.debug("payee:" + payee);
            log.debug("pay:" + pay);
            if (payee != null) {
                er.setPayeeType(payee.getPayeeType());
                er.setExpenditureProceedsId(payee.getExpenditureProceedsId());
                er.setProceedsCompany(payee.getProceedsCompany());
                er.setProceedsBank(payee.getProceedsBank());
                er.setProceedsAccount(payee.getProceedsAccount());
                er.setExpenditureBusinessCardId(payee.getExpenditureBusinessCardId());
                er.setBusinessCardName(payee.getBusinessCardName());
                er.setBusinessCardBank(payee.getBusinessCardBank());
                er.setBusinessCardAccount(payee.getBusinessCardAccount());
                er.setPayeeSummary(payee.getPayeeSummary());
            }
            if (pay != null) {
                er.setPayType(pay.getPayType());
                er.setSettleType(pay.getSettleType());
                er.setPayAccount(pay.getPayAccount());
                er.setPay(pay.getPay());
                er.setAmount(pay.getAmount());
                er.setPaySummary(pay.getPaySummary());
            }
            resps.add(er);
        });
        return ResponseDto.getSuccessResponseDto(resps);
    }

    @ApiOperation(value = "查询报账单列表(包含支付、收款信息)")
    @GetMapping(value = "/queryExpenditureReimbursement")
    public ResponseDto<Page<QueryExpenditureReimbursementResp>> queryExpenditureReimbursement(ExpenditureReimbursementReq condition,
                                                                                              @ApiParam(name = "pageNum", value = "分页页码", example = "1") Integer pageNum,
                                                                                              @ApiParam(name = "pageSize", value = "分页每页大小", example = "10") Integer pageSize,
                                                                                              @ApiParam(name = "sortField", value = "排序字段", example = "id") String sortField,
                                                                                              @ApiParam(name = "sortType", value = "排序方式", example = "desc") String sortType) {
        Page<ExpenditureReimbursementDto> pager = PageUtil.genPager(pageNum, pageSize, sortField, sortType);
        ExpenditureAccountType accountType = BaseEnum.key2Enum(ExpenditureAccountType.class, condition.getAccountType());
        Page<ExpenditureReimbursementDto> page = expenditureReimbursementService.queryExpenditureReimbursement(pager, condition, accountType);
        Page<QueryExpenditureReimbursementResp> resps = PageUtil.copyPage(page, QueryExpenditureReimbursementResp.class);
        List<Long> ids = resps.getRecords().stream().map(BaseVo::getId).collect(Collectors.toList());
        log.debug("ids:" + ids);
        final List<ExpenditureReimbursementPayeeDto> payees = new ArrayList<>();
        final List<ExpenditureReimbursementPayDto> pays = new ArrayList<>();
        if (CollUtil.isNotEmpty(ids)) {
            payees.addAll(expenditureReimbursementPayeeService.listByField("expenditureReimbursementId", ids));
            pays.addAll(expenditureReimbursementPayService.listByField("expenditureReimbursementId", ids));
        }
        log.debug("payees:" + payees);
        log.debug("pays:" + pays);
        CollUtil.forEach(resps.getRecords(), (CollUtil.Consumer<QueryExpenditureReimbursementResp>) (er, index) -> {
            ExpenditureReimbursementPayeeDto payee = payees.stream().filter(erp -> NumberUtil.equals(er.getId(), erp.getExpenditureReimbursementId())).findFirst().orElse(null);
            ExpenditureReimbursementPayDto pay = pays.stream().filter(erp -> NumberUtil.equals(er.getId(), erp.getExpenditureReimbursementId())).findFirst().orElse(null);
            log.debug("payee:" + payee);
            log.debug("pay:" + pay);
            if (payee != null) {
                er.setPayeeType(payee.getPayeeType());
                er.setExpenditureProceedsId(payee.getExpenditureProceedsId());
                er.setProceedsCompany(payee.getProceedsCompany());
                er.setProceedsBank(payee.getProceedsBank());
                er.setProceedsAccount(payee.getProceedsAccount());
                er.setExpenditureBusinessCardId(payee.getExpenditureBusinessCardId());
                er.setBusinessCardName(payee.getBusinessCardName());
                er.setBusinessCardBank(payee.getBusinessCardBank());
                er.setBusinessCardAccount(payee.getBusinessCardAccount());
                er.setPayeeSummary(payee.getPayeeSummary());
            }
            if (pay != null) {
                er.setPayType(pay.getPayType());
                er.setSettleType(pay.getSettleType());
                er.setPayAccount(pay.getPayAccount());
                er.setPay(pay.getPay());
                er.setAmount(pay.getAmount());
                er.setPaySummary(pay.getPaySummary());
            }
        });
        return ResponseDto.getSuccessResponseDto(resps);
    }

    @ApiOperation(value = "编辑保存事前用款申请单")
    @PostMapping(value = "/saveExpenditureApplication")
    public ResponseDto<ExpenditureApplicationDto> saveExpenditureApplication(@RequestBody @Valid SaveExpenditureApplicationReq vo) {
        ExpenditureApplicationDto dto = expenditureApplicationService.saveExpenditureApplication(vo);
        return ResponseDto.getSuccessResponseDto(dto);
    }

    @ApiOperation(value = "编辑提交事前用款申请单")
    @PostMapping("/submitExpenditureApplication")
    public ResponseDto<Boolean> submitExpenditureApplication(@RequestBody @Valid SubmitExpenditureApplicationReq vo) {
        expenditureApplicationService.submitExpenditureApplication(vo);
        return ResponseDto.getSuccessResponseDto(true);
    }

    @ApiOperation(value = "撤回事前用款申请单")
    @PostMapping("/revocationExpenditureApplication/{id}")
    public ResponseDto<Boolean> revocationExpenditureApplication(@PathVariable("id") Long id) {
        expenditureApplicationService.revocationExpenditureApplication(id);
        return ResponseDto.getSuccessResponseDto(true);
    }

    @ApiOperation(value = "完结事前用款申请单")
    @PostMapping("/completeExpenditureApplication/{id}")
    public ResponseDto<Boolean> completeExpenditureApplication(@PathVariable("id") Long id) {
        expenditureApplicationService.completeExpenditureApplication(id);
        return ResponseDto.getSuccessResponseDto(true);
    }

    @ApiOperation(value = "编辑保存报账单")
    @PostMapping(value = "/saveExpenditureReimbursement")
    public ResponseDto<ExpenditureReimbursementDto> saveExpenditureReimbursement(@RequestBody @Valid SaveExpenditureReimbursementReq vo) {
        ExpenditureReimbursementDto dto = expenditureReimbursementService.saveExpenditureReimbursement(vo);
        return ResponseDto.getSuccessResponseDto(dto);
    }

    @ApiOperation(value = "编辑提交报账单")
    @PostMapping("/submitExpenditureReimbursement")
    public ResponseDto<Boolean> submitExpenditureReimbursement(@RequestBody @Valid SubmitExpenditureReimbursementReq vo) {
        expenditureReimbursementService.submitExpenditureReimbursement(vo);
        return ResponseDto.getSuccessResponseDto(true);
    }

    @ApiOperation(value = "确认收单报账单")
    @PostMapping("/receiptExpenditureReimbursement/{id}")
    public ResponseDto<Boolean> receiptExpenditureReimbursement(@PathVariable("id") Long id) {
        expenditureReimbursementService.receiptExpenditureReimbursement(id);
        return ResponseDto.getSuccessResponseDto(true);
    }

    @ApiOperation(value = "编辑补充报账单收付信息")
    @PostMapping("/replenishExpenditureReimbursement")
    public ResponseDto<Boolean> replenishExpenditureReimbursement(@RequestBody @Valid ReplenishExpenditureReimbursementReq vo) {
        expenditureReimbursementService.replenishExpenditureReimbursement(vo);
        return ResponseDto.getSuccessResponseDto(true);
    }

    @ApiOperation(value = "撤回报账单")
    @PostMapping("/revocationExpenditureReimbursement/{id}")
    public ResponseDto<Boolean> revocationExpenditureReimbursement(@PathVariable("id") Long id) {
        expenditureReimbursementService.revocationExpenditureReimbursement(id);
        return ResponseDto.getSuccessResponseDto(true);
    }

}
